from typing import List, Dict, Any, Optional, Callable

from .llm import DoubaoLLM
from .executor import ActionExecutor
from .tts import SpeechFeedback
from .tools import build_default_registry
from .config import Config
from .logger import log_event


class DialogueOrchestrator:
    """Conversation-style orchestrator that plans actions, requests approval, executes, and feeds back."""

    def __init__(
        self,
        llm: Optional[DoubaoLLM] = None,
        executor: Optional[ActionExecutor] = None,
        auto_approve: Optional[bool] = None,
        approve_fn: Optional[Callable[[Dict[str, Any]], bool]] = None,
        speaker: Optional[SpeechFeedback] = None,
        max_rounds: Optional[int] = None,
    ):
        self.llm = llm or DoubaoLLM()
        self.executor = executor or ActionExecutor(llm=self.llm)
        self.registry = build_default_registry()
        self.speaker = speaker or SpeechFeedback()
        self.auto_approve = (
            Config.REQUIRE_APPROVAL is False if auto_approve is None else auto_approve
        )
        self.approve_fn = approve_fn
        self.max_rounds = max_rounds if max_rounds is not None else getattr(Config, "DIALOG_MAX_ROUNDS", 2)

    def _summarize_results(self, results: List[Dict[str, Any]]) -> str:
        parts = []
        for r in results:
            ok = "success" if r.get("success") else "fail"
            parts.append(f"[{r.get('action')}] {ok}: {r.get('detail','')}\n")
        return "".join(parts)

    def _approve_action(self, action: Dict[str, Any]) -> bool:
        if self.auto_approve:
            return True
        if self.approve_fn:
            try:
                return bool(self.approve_fn(action))
            except Exception:
                return False
        # Default: prompt in console
        try:
            summary = f"即将执行: {action.get('type')} { {k:v for k,v in action.items() if k!='type'} }"
            print(summary)
            resp = input("是否允许执行? [y/N]: ").strip().lower()
            return resp in ("y", "yes")
        except Exception:
            return False

    def _llm_plan(self, text: str) -> List[Dict[str, Any]]:
        """Plan actions using LLM with tool hints; fallback to rule-based parse."""
        try:
            hints = self.registry.prompt_hints()
            # Prefer tool-aware parsing when LLM is configured
            if self.llm.available():
                return self.llm.parse_with_tool_hints(text, hints)
            return self.llm.parse_command(text)
        except Exception:
            return []

    def run_goal(self, goal_text: str) -> List[Dict[str, Any]]:
        """Run a dialog-style loop to achieve the goal."""
        all_results: List[Dict[str, Any]] = []
        instruction = goal_text
        for round_idx in range(1, int(self.max_rounds) + 1):
            try:
                log_event("DIALOG_ROUND_BEGIN", f"round={round_idx}")
            except Exception:
                pass
            actions = self._llm_plan(instruction)
            if not actions:
                msg = "未解析到可执行动作。"
                print(msg)
                self.speaker.speak(msg)
                break
            # Approval filter
            approved: List[Dict[str, Any]] = []
            for a in actions:
                if self._approve_action(a):
                    approved.append(a)
                else:
                    log_event("ACTION_SKIPPED", f"type={a.get('type')}")
            if not approved:
                msg = "没有被批准的动作，流程结束。"
                print(msg)
                self.speaker.speak(msg)
                break
            # Execute
            results = self.executor.execute_actions(approved)
            all_results.extend(results)
            summary = self._summarize_results(results)
            print(summary)
            # 新增：输入动作统一提示（所有模式下可见）
            try:
                for r in results:
                    if r.get("action") == "computer_type":
                        msg = ("输入文本成功" if r.get("success") else "输入失败，请检查焦点")
                        print(msg)
                        try:
                            log_event("TYPE_TEXT_FEEDBACK", msg)
                        except Exception:
                            pass
            except Exception:
                pass
            # Voice feedback for key steps
            try:
                self.speaker.speak("已完成一轮操作")
            except Exception:
                pass
            # Stop if clarification requested or all succeeded with no further plan
            if any(r.get("action") == "needs_clarification" for r in results):
                break
            # Prepare next round instruction with feedback
            instruction = f"目标：{goal_text}\n执行结果：\n{summary}\n请根据结果继续完成目标。"
        return all_results